<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Visualization Dashboard</title>
    <link rel="stylesheet" href="d3-geomap/dist/d3-geomap.css">
    <style>
        #container {
            display: flex;
            justify-content: space-around;
            height: 100vh;
        }
        #bubble_chart, #map {
            flex: 1;
            min-width: 1000px;
            min-height: 0;
        }
        #bar_chart {
            width: 100%;
            height: 450px;
        }
    </style>
</head>
<body>

<h1 style="text-align: center;">Visualization Dashboard</h1>

<!-- 输入框和下拉列表 -->
<div style="text-align: center;">
    <input type="number" id="yearInput" value="1800" min="1800" max="2100">
    <select id="attributeSelect">
        <option value="income">Income</option>
        <option value="population">Population</option>
        <option value="lifeExpectancy">Life Expectancy</option>
    </select>
</div>

<!-- 容器 -->
<div id="container">
    <div id="bubble_chart"></div>
    <div id="map" class="d3-geomap"></div>
</div>
<div id="bar_chart"></div>

<!-- 加载脚本 -->
<script src="d3.v6.min.js"></script>
<script src="topojson.min.js"></script>
<script src="d3-geomap/dist/d3-geomap.min.js"></script>

<script>
    // 绘制气泡图
    const width = 960;
    const height = 500;
    const svg = d3.select("#bubble_chart")
        .append("svg")
        .attr("width", width)
        .attr("height", height);

    const renderBubbleChart = (data, selectedYear, selectedAttribute) => {
        const filteredData = data.filter(d => +d.year === selectedYear);
        svg.selectAll("*").remove();

        const x = d3.scaleLog()
            .domain(d3.extent(filteredData, d => +d.income))
            .range([0, width]);

        const y = d3.scaleLinear()
            .domain(d3.extent(filteredData, d => +d.lifeExpectancy))
            .range([height, 0]);

        const r = d3.scaleSqrt()
            .domain(d3.extent(filteredData, d => +d.population))
            .range([0, 40]);

        const color = d3.scaleOrdinal(d3.schemeCategory10);

        svg.selectAll("circle")
            .data(filteredData)
            .enter()
            .append("circle")
            .attr("cx", d => x(d.income))
            .attr("cy", d => y(d.lifeExpectancy))
            .attr("r", d => r(d.population))
            .attr("fill", d => color(d.region));
    };

    // 绘制地图
    const countryMapping = {
        "Afghanistan": "AFG", "Albania": "ALB", "Algeria": "DZA", "Andorra": "AND", "Angola": "AGO",
        // ... (省略其他国家的映射，完整代码中应包括所有国家)
        "Zambia": "ZMB", "Zimbabwe": "ZWE"
    };

    function drawMap(year, selectedAttribute) {
        d3.csv('data/newData.csv').then(data => {
            var filteredData = data.filter(d => d.year == year);
            filteredData.forEach(d => d.iso3 = countryMapping[d.name]);
            d3.select('#map').selectAll("*").remove();
            var map = d3.choropleth()
                .geofile('d3-geomap/dist/topojson/world/countries.json')
                .colors(d3.schemePaired)
                .format(d3.format(',.02f'))
                .legend(true)
                .unitId('iso3')
                .column(selectedAttribute);
            d3.select('#map').datum(filteredData).call(map.draw);
        });
    }

    // 设置输入框和下拉列表的监听器
    var yearInput = document.getElementById('yearInput');
    var attributeSelect = document.getElementById('attributeSelect');
    yearInput.addEventListener('input', function () {
        var selectedYear = parseInt(yearInput.value);
        var selectedAttribute = attributeSelect.value;
        d3.csv('data/newData.csv').then(data => {
            renderBubbleChart(data, selectedYear, selectedAttribute);
        });
        drawMap(selectedYear, selectedAttribute);
        updateBarChart(selectedYear, selectedAttribute);
    });
    attributeSelect.addEventListener('change', function () {
        var selectedYear = parseInt(yearInput.value);
        var selectedAttribute = attributeSelect.value;
        d3.csv('data/newData.csv').then(data => {
            renderBubbleChart(data, selectedYear, selectedAttribute);
        });
        drawMap(selectedYear, selectedAttribute);
        updateBarChart(selectedYear, selectedAttribute);
    });

    // 绘制柱状图
    const margin = { top: 10, right: 30, bottom: 100, left: 40 },
        barWidth = 460 - margin.left - margin.right,
        barHeight = 450 - margin.top - margin.bottom;

    const barSvg = d3.select("#bar_chart")
        .append("svg")
        .attr("width", barWidth + margin.left + margin.right)
        .attr("height", barHeight + margin.top + margin.bottom)
        .append("g")
        .attr("transform", `translate(${margin.left},${margin.top})`);

    function updateBarChart(year, attribute) {
        d3.csv("/data/newData.csv").then(data => {
            const filteredData = data.filter(d => d.year == year);
            const summedData = d3.rollup(filteredData, v => d3.sum(v, d => +d[attribute]), d => d.region);
            const dataArray = Array.from(summedData, ([key, value]) => ({ region: key, value }));

            const x = d3.scaleBand()
                .range([0, barWidth])
                .domain(dataArray.map(d => d.region))
                .padding(0.2);
            barSvg.selectAll(".x-axis").remove();
            barSvg.append("g")
                .attr("class", "x-axis")
                .attr("transform", `translate(0, ${barHeight})`)
                .call(d3.axisBottom(x))
                .selectAll("text")
                .attr("transform", "translate(-10,0)rotate(-45)")
                .style("text-anchor", "end");

            const y = d3.scaleLinear()
                .domain([0, d3.max(dataArray, d => d.value)])
                .range([barHeight, 0]);
            barSvg.selectAll(".y-axis").remove();
            barSvg.append("g")
                .attr("class", "y-axis")
                .call(d3.axisLeft(y));

            const bars = barSvg.selectAll(".bar")
                .data(dataArray);
            bars.enter()
                .append("rect")
                .attr("class", "bar")
                .merge(bars)
                .attr("x", d => x(d.region))
                .attr("width", x.bandwidth())
                .attr("y", d => y(d.value))
                .attr("height", d => barHeight - y(d.value))
                .attr("fill", "#69b3a2");
            bars.exit().remove();
        });
    }

    // 初始化图像
    d3.csv('data/newData.csv').then(data => {
        renderBubbleChart(data, 1800, 'income');
    });
    drawMap(1800, 'income');
    updateBarChart(1800, "income");
</script>
</body>
</html>
